﻿#region Copyright

// All Material Copyright © 2010 Dynamic Concepts Development Corp., All Rights Reserved.
//      Portions Copyright © 1984-2009 Dynamic Concepts Development Corp., All Rights Reserved.
// For further information please contact: SoftwareSupport@dynconcepts.com
// Dynamic Concepts Development Corp.  311 W 57th St. Suite #422, New York, NY 10019

#endregion

#region Using References

using System;
using System.Collections.Generic;
using System.Windows.Threading;

#endregion

namespace DynConDevCorp.OpenArch.SupportLibrary.ParallelExecution
{
    public abstract class ParallelExecutionBase
    {
        #region Constructors

        protected ParallelExecutionBase(Object owner, Dispatcher owningDispatcher)
        {
            if (!ReferenceEquals(owningDispatcher, Dispatcher.CurrentDispatcher))
                throw new InvalidOperationException();
            r_Owner = owner ?? sr_DefaultOwner;
            r_OwningDispatcher = owningDispatcher;
        }

        #endregion

        #region Public Methods

        public static bool IsIdle(Object owner)
        {
            lock (sr_SyncRoot)
            {
                List<ParallelExecutionBase> list = GetList(owner);
                return list.Count == 0;
            }
        }

        #endregion

        #region Protected Methods

        protected void ExecutionComplete()
        {
            lock (sr_SyncRoot)
            {
                List<ParallelExecutionBase> list = GetList();
                if (!list.Contains(this))
                    throw new InvalidOperationException();
                list.Remove(this);
                if (list.Count == 0)
                    Fire_OwnerListEmptied();
            }
        }

        protected void ExecutionStarted()
        {
            if (!ReferenceEquals(r_OwningDispatcher, Dispatcher.CurrentDispatcher))
                throw new InvalidOperationException();
            lock (sr_SyncRoot)
            {
                List<ParallelExecutionBase> list = GetList();
                list.Add(this);
            }
        }

        #endregion

        #region Private Methods

        private void Fire_OwnerListEmptied()
        {
            EventHandler<EventArgs> shadow = OwnerListEmptied;
            if (shadow != null)
            {
                shadow(r_Owner, new EventArgs());
            }
        }

        private List<ParallelExecutionBase> GetList()
        {
            return GetList(r_Owner);
        }

        private static List<ParallelExecutionBase> GetList(Object owner)
        {
            List<ParallelExecutionBase> retVal;
            if (!sr_Dictionary.TryGetValue(owner, out retVal))
            {
                retVal = new List<ParallelExecutionBase>();
                sr_Dictionary.Add(owner, retVal);
            }
            return retVal;
        }

        #endregion

        #region Static Fields and Constants

        public static EventHandler<EventArgs> OwnerListEmptied;
        private static readonly Object sr_DefaultOwner = new Object();
        private static readonly Dictionary<Object, List<ParallelExecutionBase>> sr_Dictionary = new Dictionary<Object, List<ParallelExecutionBase>>();
        private static readonly Object sr_SyncRoot = new Object();

        #endregion

        #region Instance Fields (ReadOnly)

        protected readonly Object r_Owner;
        protected readonly Dispatcher r_OwningDispatcher;

        #endregion
    }
}